package com.tea.quartz.task;

import com.tea.common.utils.StringUtils;
import com.tea.common.utils.email.EmailUtil;
import com.tea.funct.domain.TeaFixation;
import com.tea.funct.domain.TeaPriceDetails;
import com.tea.funct.domain.TeaProduct;
import com.tea.funct.domain.TeaSubclass;
import com.tea.funct.service.ITeaFixationService;
import com.tea.funct.service.ITeaPriceDetailsService;
import com.tea.funct.service.ITeaProductService;
import com.tea.funct.service.ITeaSubclassService;
import com.tea.funct.utils.domain.*;
import com.tea.funct.utils.util.PullDataUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.math.BigDecimal;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;

/**
 * 定时任务调度测试
 *
 * @author Sophia
 */
@Slf4j
@Component("ryTask")
public class RyTask {

    @Autowired
    private ITeaProductService teaProductService;
    @Autowired
    private ITeaPriceDetailsService teaPriceDetailsService;
    @Autowired
    private PullDataUtil pullDataUtil;
    @Autowired
    private ITeaSubclassService teaSubclassService;
    @Autowired
    private ITeaFixationService teaFixationService;
    @Autowired
    private EmailUtil emailUtil;

    public void ryMultipleParams(String s, Boolean b, Long l, Double d, Integer i) {
        System.out.println(StringUtils.format("执行多参方法： 字符串类型{}，布尔类型{}，长整型{}，浮点型{}，整形{}", s, b, l, d, i));
    }

    public void ryParams(String params) {
        System.out.println("执行有参方法：" + params);
    }

    public void ryNoParams() {
        System.out.println("执行无参方法");
    }

    /**
     * 将最新产品数据导入到历史明细表中
     */
    public void syncProductInfoEveryDay() {
        log.info("拉取当日产品信息，同步到产品历史记录表");
        List<TeaProduct> teaProducts = teaProductService.selectTeaProductList(null);
        if (teaProducts != null && teaProducts.size() > 0) {
            log.info("共获取到{}条产品信息", teaProducts.size());
            List<Long> productIds = teaProducts.stream().map(TeaProduct::getId).collect(Collectors.toList());
            List<Long> detailIds = teaPriceDetailsService.selectHasInPriceDetailsListByProductIdsAndTime(productIds);
            if (productIds != null && detailIds != null) {
                log.info("查询到相同产品，相同时间的明细共有{}条", detailIds.size());
                productIds.removeAll(detailIds);
                log.info("去除已有的明细，插入未有的产品明细信息{}条", productIds.size());
                log.info("产品id为：{}", productIds);
                if (productIds != null && productIds.size() > 0) {
                    Integer success = teaPriceDetailsService.syncInsertTeaPriceDetailsData(productIds);
                    log.info("成功批量同步{}条产品数据到产品历史明细表", success);
                } else {
                    log.info("去除已有的明细后，无需要同步的产品信息!");
                }
            } else {
                log.info("无需要同步到历史明细表的产品数据信息!");
            }
        } else {
            log.info("没有查询到相关产品信息!");
        }
    }

    /**
     * 拉取每天产品最新的价位信息(根据产品id一条一条拉取) 不推荐，太慢了
     */
    public void pullProductPriceEveryDayByProductFlagId() throws InterruptedException {
        TeaFixation teaFixation = teaFixationService.selectTeaFixationByFeild("pullDataTokenFlag");
        if (teaFixation == null) {
            log.info("请先在静态配置里配置拉取数据的token信息...");
            return;
        }
        String token = teaFixation.getFixationImgConf();
        log.info("拉取每天产品最新的价位信息到产品表");
        SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd");
        Date date = new Date(); // 获取当前时间
        String url = "https://www.yanjiuchacha.com/api/market/atProduct/useTheNewQueryPageList?pageNo=1&pageSize=15&productType={productType}&manufacturerId=&productName={productName}&type=";
        List<TeaProduct> teaProducts = teaProductService.selectTeaProductList(null);
        List<String> errorUrlList = new ArrayList<>();
        if (teaProducts != null && teaProducts.size() > 0) {
            log.info("共获取到{}条产品信息", teaProducts.size());
            List<TeaProduct> list = new ArrayList<>();
            for (TeaProduct teaProduct : teaProducts) {
                String urlTemp = url.replace("{productType}", teaProduct.getCategoryId().toString()); // 产品大类
                urlTemp = urlTemp.replace("{productName}", teaProduct.getProductName()); // 产品名称
                PullProductInfo pullProductInfo = (PullProductInfo) pullDataUtil.getMethodPull(urlTemp, token, PullProductInfo.class);
                if (pullProductInfo != null) {
                    if (pullProductInfo.getCode() == 200) {

                        ProductInfoResult result = pullProductInfo.getResult();
                        if (result != null) {
                            List<ProductInfoRecord> records = result.getRecords();
                            if (records != null && records.size() > 0) {
                                for (ProductInfoRecord p : records) {
                                    if (StringUtils.equals(p.getProductId(), teaProduct.getProductFlagId())) {
                                        teaProduct.setProductPrice(p.getProductMoney() != null ? new BigDecimal(p.getProductMoney()) : null);
                                        teaProduct.setGuidePrice(p.getGuidePrice() != null ? new BigDecimal(p.getGuidePrice()) : null);
                                        teaProduct.setTradePrice(p.getTradePrice() != null ? new BigDecimal(p.getTradePrice()) : null);
                                        teaProduct.setBiliPrice(p.getBili() != null ? new BigDecimal(p.getBili()) : null);
                                        if (StringUtils.isBlank(p.getBili()) || StringUtils.equals(p.getBili(), "0.0")) {
                                            teaProduct.setBiliType("0"); // 0平，1涨，2降
                                        } else {
                                            teaProduct.setBiliType(p.getType()); // 1涨，2降
                                        }
                                        teaProduct.setCreateTime(date);
                                        list.add(teaProduct);
                                        log.info("获取到相同数据，则终止！");
                                        // teaProductService.updateTeaProduct(teaProduct);
                                        Thread.sleep(30000);
                                        break;
                                    }
                                }
                            }
                        }
                    } else {
                        errorUrlList.add(urlTemp);
                        log.info("请求结果为空，记录并等待10s请求下一条！");
                        Thread.sleep(10000);
                    }
                }
            }
            if (list != null && list.size() > 0) {
                teaProductService.updateTeaProductAll(list);
                log.info("产品数据信息批量修改成功!");
            }
            if (errorUrlList != null && errorUrlList.size() > 0) {
                log.info("失败获取产品信息的条数为: {};并持久化到文件", errorUrlList.size());
                this.saveErrorUrlToFile("/home/sophia/application/teaWine/pullData/pullProductPriceEveryDayUrl" + sdf.format(date) + ".txt", errorUrlList);
            }
            // TODO 将持久化的数据重新读取并循环获取数据入库
        } else {
            log.info("没有查询到相关产品信息!");
        }
    }

    /**
     * 拉取每天产品最新的价位信息并更新到数据库(根据产品所属小类id，批量拉取) 推荐
     */
    public void pullProductPriceEveryDay(Integer defaultPullNum) throws InterruptedException {
        if (defaultPullNum == null) {
            defaultPullNum = 4; // 默认拉取4次
        }
        TeaFixation teaFixation = teaFixationService.selectTeaFixationByFeild("pullDataTokenFlag");
        if (teaFixation == null) {
            log.info("请先在静态配置里配置拉取数据的token信息...");
            return;
        }
        Boolean isTokenDisable = false;
        String token = teaFixation.getFixationImgConf();
        log.info("拉取每天产品最新的价位信息到产品表");
        SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd");
        Date date = new Date(); // 获取当前时间
        String filePath = "/home/sophia/application/teaWine/pullData/pullProductPriceEveryDayUrl{fileFlag}.txt";
        filePath = filePath.replace("{fileFlag}", sdf.format(date));
        // https://www.yanjiuchacha.com/api/market/atProduct/useTheNewQueryPageList?pageNo=1&pageSize=15&productType=2&manufacturerId=&productName=&
        String url = "https://www.yanjiuchacha.com/api/market/atProduct/useTheNewQueryPageList?pageNo={pageNum}&pageSize=15&productType={productType}&manufacturerId={subclass}&productName=&";
        List<TeaSubclass> list = teaSubclassService.selectTeaSubclassList(null);
        List<String> errorUrlList = new ArrayList<>();
        if (list != null && list.size() > 0) {
            for (TeaSubclass teaSubclass : list) {
                if (StringUtils.isBlank(teaSubclass.getRemark()) || teaSubclass.getCategoryId() == null) {
                    log.info("小类参数配置不全，则跳过该条数据拉取...");
                    continue;
                }
                String urlTemp = url.replace("{pageNum}", "1"); // 默认第一页
                urlTemp = urlTemp.replace("{subclass}", teaSubclass.getRemark());
                urlTemp = urlTemp.replace("{productType}", teaSubclass.getCategoryId().toString());
                // 第一次请求
                PullProductInfo pullProductInfo = (PullProductInfo) pullDataUtil.getMethodPull(urlTemp, token, PullProductInfo.class);
                if (pullProductInfo != null) {
                    if (pullProductInfo.getCode() == 200) {
                        ProductInfoResult result = pullProductInfo.getResult();
                        Integer pages = result.getPages();
                        if (result != null) {
                            log.info("批量修改产品价格到产品表...");
                            this.updateProductBySubclass(teaSubclass.getSubclassName(), result.getRecords(), date);
                        }
                        if (pages > 1) {
                            // 递归调用数据
                            for (Integer i = 2; i <= pages; i++) {
                                String rUrl = url.replace("{pageNum}", i.toString()); // 默认第一页
                                rUrl = rUrl.replace("{subclass}", teaSubclass.getRemark());
                                rUrl = rUrl.replace("{productType}", teaSubclass.getCategoryId().toString());
                                try {
                                    List<ProductInfoRecord> records = this.getProductRecordsBySubclassId(rUrl, token);
                                    if (records == null) {
                                        errorUrlList.add(rUrl);
                                        log.info("请求结果为空，记录并等待20s请求下一条！");
                                        Thread.sleep(20000);
                                    } else {
                                        this.updateProductBySubclass(teaSubclass.getSubclassName(), records, date);
                                    }
                                } catch (Exception e) {
                                    errorUrlList.add(rUrl);
                                    log.info("请求报错，记录并等待20s请求下一条！");
                                    Thread.sleep(20000);
                                }
                            }
                        }
                    } else if (pullProductInfo.getCode() == 500 && StringUtils.containsAny(pullProductInfo.getMessage(), "没有权限", "权限")) {
                        log.error("拉取数据时提示请求无权限：则证明token不正确或会员已过期, 发送邮件提醒更新token信息!");
                        this.sendTokenDisableMessage();
                        isTokenDisable = true;
                        break;
                    } else {
                        errorUrlList.add(urlTemp);
                        log.info("请求结果为空，记录并等待20s请求下一条！");
                        Thread.sleep(20000);
                    }
                } else {
                    log.error("拉取数据出现异常：则证明token不正确或已过期, 发送邮件提醒更新token信息");
                    this.sendTokenDisableMessage();
                    isTokenDisable = true;
                    break;
                }
            }
        }
        if (errorUrlList != null && errorUrlList.size() > 0) {
            log.info("失败获取产品信息的条数为: {};并持久化到文件", errorUrlList.size());
            this.saveErrorUrlToFile(filePath, errorUrlList);
        }
        // TODO 将持久化的数据重新读取并循环获取数据入库
        if (isTokenDisable) {
            return;
        }
        List<String> urlList = this.readFileToList(filePath);
        if (urlList != null && urlList.size() > 0) {
            // 重新记录请求错误的url信息(4次循环几乎可以搞定)
            log.info("失败数据重新拉取次数：{}", defaultPullNum);
            for (int j = 0; j < defaultPullNum; j++) {
                log.info("第{}次循环拉取数据...", j + 1);
                errorUrlList = new ArrayList<>();
                // 拉取产品数据
                for (String eUrl : urlList) {
                    String targetStr = "manufacturerId=";
                    String targetStr1 = "&productName=&";
                    int i = eUrl.indexOf(targetStr);
                    String subId = eUrl.substring(i + targetStr.length()).replace(targetStr1, "");
                    log.info("小类id：{}", subId);
                    TeaSubclass tsc = new TeaSubclass();
                    tsc.setRemark(subId);
                    List<TeaSubclass> eList = teaSubclassService.selectTeaSubclassList(tsc);
                    TeaSubclass teaSubclass = eList.get(0);
                    // 第一次请求
                    PullProductInfo pullProductInfo = (PullProductInfo) pullDataUtil.getMethodPull(eUrl, token, PullProductInfo.class);
                    if (pullProductInfo != null) {
                        if (pullProductInfo.getCode() == 200) {
                            ProductInfoResult result = pullProductInfo.getResult();
                            if (result != null) {
                                log.info("批量插入到产品表...");
                                this.updateProductBySubclass(teaSubclass.getSubclassName(), result.getRecords(), date);
                            }
                        } else if (pullProductInfo.getCode() == 500 && StringUtils.containsAny(pullProductInfo.getMessage(), "没有权限", "权限")) {
                            log.error("拉取数据时提示请求无权限：则证明token不正确或会员已过期, 发送邮件提醒更新token信息!");
                            this.sendTokenDisableMessage();
                            isTokenDisable = true;
                            break;
                        } else {
                            errorUrlList.add(eUrl);
                            log.info("请求状态码为500，记录并等待20s请求下一条！");
                            Thread.sleep(20000);
                        }
                    } else {
                        log.error("拉取数据出现异常：则证明token不正确或已过期, 发送邮件提醒更新token信息");
                        this.sendTokenDisableMessage();
                        isTokenDisable = true;
                        break;
                    }
                }
                if (isTokenDisable) {
                    break;
                }
                if (errorUrlList != null && errorUrlList.size() > 0) {
                    log.info("第{}次拉取失败产品信息的条数为: {}", j + 1, errorUrlList.size());
                    this.saveErrorUrlToFile(filePath, errorUrlList);
                }
            }
        }
    }

    public void pullProductInfoByFile() throws InterruptedException {
        log.info("拉取未成功的产品数据信息...");
        SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd");
        Date date = new Date(); // 获取当前时间
        String filePath = "/home/sophia/application/teaWine/pullData/pullProductPriceEveryDayUrl{fileFlag}.txt";
        filePath = filePath.replace("{fileFlag}", sdf.format(date));
        List<String> urlList = this.readFileToList(filePath);
        List<String> errorUrlList = new ArrayList<>();
        if (urlList != null && urlList.size() > 0) {
            TeaFixation teaFixation = teaFixationService.selectTeaFixationByFeild("pullDataTokenFlag");
            if (teaFixation == null) {
                log.info("请先在静态配置里配置拉取数据的token信息...");
                return;
            }
            String token = teaFixation.getFixationImgConf();
            // 拉取产品数据
            for (String eUrl : urlList) {
                String targetStr = "manufacturerId=";
                String targetStr1 = "&productName=&";
                int i = eUrl.indexOf(targetStr);
                String subId = eUrl.substring(i + targetStr.length()).replace(targetStr1, "");
                log.info("小类id：{}", subId);
                TeaSubclass tsc = new TeaSubclass();
                tsc.setRemark(subId);
                List<TeaSubclass> eList = teaSubclassService.selectTeaSubclassList(tsc);
                TeaSubclass teaSubclass = eList.get(0);
                // 第一次请求
                PullProductInfo pullProductInfo = (PullProductInfo) pullDataUtil.getMethodPull(eUrl, token, PullProductInfo.class);
                if (pullProductInfo != null) {
                    if (pullProductInfo.getCode() == 200) {
                        ProductInfoResult result = pullProductInfo.getResult();
                        if (result != null) {
                            log.info("批量插入到产品表...");
                            this.updateProductBySubclass(teaSubclass.getSubclassName(), result.getRecords(), date);
                        }
                    } else if (pullProductInfo.getCode() == 500 && StringUtils.containsAny(pullProductInfo.getMessage(), "没有权限", "权限")) {
                        log.error("拉取数据时提示请求无权限：则证明token不正确或会员已过期, 发送邮件提醒更新token信息!");
                        this.sendTokenDisableMessage();
                        break;
                    } else {
                        errorUrlList.add(eUrl);
                        log.info("请求状态码为500，记录并等待20s请求下一条！");
                        Thread.sleep(20000);
                    }
                } else {
                    log.error("拉取数据出现异常：则证明token不正确或已过期, 发送邮件提醒更新token信息");
                    this.sendTokenDisableMessage();
                    break;
                }
            }
            if (errorUrlList != null && errorUrlList.size() > 0) {
                log.info("拉取失败产品信息的条数为:{}", errorUrlList.size());
                this.saveErrorUrlToFile(filePath, errorUrlList);
            }
        }
    }
    
    /**
     * 根据产品id拉取产品历史明细信息
     *
     * @return
     */
    public void pullProductDetailByTime(Integer defaultPullNum, String startTime, String endTime) throws ParseException, InterruptedException {
        SimpleDateFormat sdf1 = new SimpleDateFormat("yyyyMMdd");
        String filePath = "/home/sophia/application/teaWine/pullData/pullDetailsErrorUrl{fileFlag}.txt";
        filePath = filePath.replace("{fileFlag}", sdf1.format(new Date()));

        if (defaultPullNum == null) {
            defaultPullNum = 4; // 默认失败后重新拉取4次
        }
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
        TeaFixation teaFixation = teaFixationService.selectTeaFixationByFeild("pullDataTokenFlag");
        if (teaFixation == null) {
            log.info("请先在静态配置里配置拉取数据的token信息...");
            return;
        }
        Boolean isTokenDisable = false;
        String token = teaFixation.getFixationImgConf();
        String url = "https://www.yanjiuchacha.com/api/market/atProductMoney/useTheNewQueryList?productId={productId}&startDay={startDay}&endDay={endDay}";
        List<TeaProduct> teaProducts = teaProductService.selectTeaProductList(null);
        List<String> errorUrlList = new ArrayList<>();

        if (teaProducts != null && teaProducts.size() > 0) {
            for (TeaProduct teaProduct : teaProducts) {
                if (StringUtils.isBlank(teaProduct.getProductFlagId())) {
                    log.info("该产品{} 不存在产品标识id", teaProduct.getProductName());
                    continue;
                }
                String urlTemp = url.replace("{productId}", teaProduct.getProductFlagId()); // 产品id
                urlTemp = urlTemp.replace("{startDay}", startTime); // 开始时间 2024-06-14
                urlTemp = urlTemp.replace("{endDay}", endTime); // 结束时间 2024-06-20
                PullProductDetailInfo pullProductDetailInfo = (PullProductDetailInfo) pullDataUtil.getMethodPull(urlTemp, token, PullProductDetailInfo.class);
                if (pullProductDetailInfo != null) {
                    if (pullProductDetailInfo.getCode() == 200) {
                        List<PullProductDetailResult> result = pullProductDetailInfo.getResult();
                        List<TeaPriceDetails> list = new ArrayList<>();
                        if (result != null && result.size() > 0) {
                            for (PullProductDetailResult dr : result) {
                                TeaPriceDetails teaPriceDetails = new TeaPriceDetails();
                                teaPriceDetails.setProductFlagId(teaProduct.getProductFlagId());
                                teaPriceDetails.setProductId(teaProduct.getId());
                                teaPriceDetails.setProductPrice(dr.getMoney() != null ? new BigDecimal(dr.getMoney()) : null);
                                teaPriceDetails.setGuidePrice(dr.getGuidePrice() != null ? new BigDecimal(dr.getGuidePrice()) : null);
                                teaPriceDetails.setTradePrice(dr.getTradePrice() != null ? new BigDecimal(dr.getTradePrice()) : null);
                                teaPriceDetails.setBiliPrice(dr.getBili() != null ? new BigDecimal(dr.getBili()) : null);
                                teaPriceDetails.setCreateTime(sdf.parse(dr.getMoneyDay()));
                                if (StringUtils.isBlank(dr.getBili()) || StringUtils.equals(dr.getBili(), "0.0")) {
                                    teaPriceDetails.setBiliType("0"); // 0平，1涨，2降
                                } else {
                                    teaPriceDetails.setBiliType(dr.getType()); // 1涨，2降
                                }
                                teaPriceDetails.setUpdateTime(new Date());
                                list.add(teaPriceDetails);
                            }
                        }
                        if (list != null && list.size() > 0) {
                            teaPriceDetailsService.insertOrUpdateDetails(list);
                            // teaPriceDetailsService.insertTeaPriceDetailsAll(list);
                            log.info("产品ID为{}的历史明细批量插入成功!", teaProduct.getProductFlagId());
                        }
                        log.info("获取到数据为：{}", result);
                    } else if (pullProductDetailInfo.getCode() == 500 && StringUtils.containsAny(pullProductDetailInfo.getMessage(), "没有权限", "权限")) {
                        log.error("拉取数据时提示请求无权限：则证明token不正确或会员已过期, 发送邮件提醒更新token信息!");
                        this.sendTokenDisableMessage();
                        isTokenDisable = true;
                        break;
                    } else {
                        errorUrlList.add(urlTemp);
                        log.info("请求错误，记录并等待20s请求下一条！");
                        Thread.sleep(20000);
                    }
                } else {
                    log.error("拉取数据出现异常：则证明token不正确或已过期, 发送邮件提醒更新token信息");
                    this.sendTokenDisableMessage();
                    isTokenDisable = true;
                    break;
                }
            }
        }
        if (errorUrlList != null && errorUrlList.size() > 0) {
            log.info("失败获取明细的条数为: {}", errorUrlList.size());
            this.saveErrorUrlToFile(filePath, errorUrlList);
        }
        // TODO 将持久化的数据重新读取并循环获取数据入库
        if (isTokenDisable) {
            return;
        }
        List<String> urlList = this.readFileToList(filePath);
        if (urlList != null && urlList.size() > 0) {
            // 重新记录请求错误的url信息(4次循环几乎可以搞定)
            log.info("失败数据重新拉取次数：{}", defaultPullNum);
            for (int j = 0; j < defaultPullNum; j++) {
                log.info("第{}次循环拉取数据...", j + 1);
                errorUrlList = new ArrayList<>();
                // 拉取产品数据
                for (String cUrl : urlList) {
                    String targetStr = "productId=";
                    String targetStr1 = "&startDay=";
                    int i = cUrl.indexOf(targetStr);
                    int e = cUrl.indexOf(targetStr1);
                    String productId = cUrl.substring(i + targetStr.length(), e);
                    log.info("产品id：{}", productId);
                    TeaProduct teaProduct = teaProductService.selectTeaProductByFlagId(productId);
                    PullProductDetailInfo pullProductDetailInfo = (PullProductDetailInfo) pullDataUtil.getMethodPull(cUrl, token, PullProductDetailInfo.class);
                    if (pullProductDetailInfo != null) {
                        if (pullProductDetailInfo.getCode() == 200) {
                            List<PullProductDetailResult> result = pullProductDetailInfo.getResult();
                            List<TeaPriceDetails> list = new ArrayList<>();
                            if (result != null && result.size() > 0) {
                                for (PullProductDetailResult dr : result) {
                                    TeaPriceDetails teaPriceDetails = new TeaPriceDetails();
                                    teaPriceDetails.setProductFlagId(teaProduct.getProductFlagId());
                                    teaPriceDetails.setProductId(teaProduct.getId());
                                    teaPriceDetails.setProductPrice(dr.getMoney() != null ? new BigDecimal(dr.getMoney()) : null);
                                    teaPriceDetails.setGuidePrice(dr.getGuidePrice() != null ? new BigDecimal(dr.getGuidePrice()) : null);
                                    teaPriceDetails.setTradePrice(dr.getTradePrice() != null ? new BigDecimal(dr.getTradePrice()) : null);
                                    teaPriceDetails.setBiliPrice(dr.getBili() != null ? new BigDecimal(dr.getBili()) : null);
                                    teaPriceDetails.setCreateTime(sdf1.parse(dr.getMoneyDay()));
                                    if (StringUtils.isBlank(dr.getBili()) || StringUtils.equals(dr.getBili(), "0.0")) {
                                        teaPriceDetails.setBiliType("0"); // 0平，1涨，2降
                                    } else {
                                        teaPriceDetails.setBiliType(dr.getType()); // 1涨，2降
                                    }
                                    teaPriceDetails.setUpdateTime(new Date());
                                    list.add(teaPriceDetails);
                                }
                            }
                            if (list != null && list.size() > 0) {
                                teaPriceDetailsService.insertOrUpdateDetails(list);
                                // teaPriceDetailsService.insertTeaPriceDetailsAll(list);
                                log.info("产品ID为{}的历史明细批量插入成功!", teaProduct.getProductFlagId());
                            }
                            log.info("获取到数据为：{}", result);
                        } else if (pullProductDetailInfo.getCode() == 500 && StringUtils.containsAny(pullProductDetailInfo.getMessage(), "没有权限", "权限")) {
                            log.error("拉取数据时提示请求无权限：则证明token不正确或会员已过期, 发送邮件提醒更新token信息!");
                            this.sendTokenDisableMessage();
                            isTokenDisable = true;
                            break;
                        } else {
                            errorUrlList.add(cUrl);
                            log.info("请求错误，记录并等待20s请求下一条！");
                            Thread.sleep(20000);
                        }
                    } else {
                        log.error("拉取数据出现异常：则证明token不正确或已过期, 发送邮件提醒更新token信息");
                        this.sendTokenDisableMessage();
                        isTokenDisable = true;
                        break;
                    }
                }
                if (isTokenDisable) {
                    break;
                }
                if (errorUrlList != null && errorUrlList.size() > 0) {
                    log.info("第{}次拉取失败产品明细信息的条数为: {}", j + 1, errorUrlList.size());
                    this.saveErrorUrlToFile(filePath, errorUrlList);
                }
            }
        }
    }

    private void updateProductBySubclass(String subclassName, List<ProductInfoRecord> records, Date nowDay) {
        if (records != null && records.size() > 0) {
            List<TeaProduct> teaProducts = new ArrayList<>();
            for (ProductInfoRecord p : records) {
                TeaProduct teaProduct = new TeaProduct();
                teaProduct.setProductPrice(p.getProductMoney() != null ? new BigDecimal(p.getProductMoney()) : null);
                teaProduct.setGuidePrice(p.getGuidePrice() != null ? new BigDecimal(p.getGuidePrice()) : null);
                teaProduct.setTradePrice(p.getTradePrice() != null ? new BigDecimal(p.getTradePrice()) : null);
                teaProduct.setBiliPrice(p.getBili() != null ? new BigDecimal(p.getBili()) : null);
                if (StringUtils.isBlank(p.getBili()) || StringUtils.equals(p.getBili(), "0.0")) {
                    teaProduct.setBiliType("0"); // 0平，1涨，2降
                } else {
                    teaProduct.setBiliType(p.getType()); // 1涨，2降
                }
                teaProduct.setProductFlagId(p.getProductId());
                teaProduct.setCreateTime(nowDay);
                teaProduct.setUpdateTime(new Date());
                teaProducts.add(teaProduct);
            }
            if (teaProducts != null && teaProducts.size() > 0) {
                teaProductService.updateTeaProductAllByFlagId(teaProducts);
                log.info("小类为{} 的数据批量更新完成!", subclassName);
            }
        }
    }

    private List<ProductInfoRecord> getProductRecordsBySubclassId(String url, String token) {
        log.info("请求拉取数据：{}", url);
        // 第一次请求
        PullProductInfo pullProductInfo = (PullProductInfo) pullDataUtil.getMethodPull(url, token, PullProductInfo.class);
        if (pullProductInfo != null) {
            if (pullProductInfo.getCode() == 200) {
                ProductInfoResult result = pullProductInfo.getResult();
                if (result != null) {
                    List<ProductInfoRecord> records = result.getRecords();
                    return records;
                }
            } else {
                log.error("请求错误1：{}", pullProductInfo);
                throw new RuntimeException("请求错误!");
            }
        } else {
            log.error("请求错误2：{}", pullProductInfo);
            throw new RuntimeException("请求错误!");
        }
        return null;
    }

    private List<String> readFileToList(String filePath) {
        List<String> list = new ArrayList<>();
        File file = new File(filePath);
        if (!file.exists()) {
            log.info("文件{} 不存在！无需重新拉取数据!", filePath);
            return list;
        }
        try (BufferedReader reader = new BufferedReader(new FileReader(filePath))) {
            String line;
            while ((line = reader.readLine()) != null) {
                list.add(line);
            }
            log.info("共查询到{}条需要从文件中处理的数据", list.size());
        } catch (Exception e) {
            log.error("文件转list 出现异常：{}", e.getMessage());
            log.error(e.getMessage(), e);
        }
        return list;
    }

    private void saveErrorUrlToFile(String fileName, List<String> list) {
        try {
            Files.write(Paths.get(fileName), list);
            log.info("文件{} 写入成功", fileName);
        } catch (IOException e) {
            log.error("写入文件时出现异常：{}", e.getMessage());
            log.error(e.getMessage(), e);
        }
    }

    /**
     * 发送token不可用的邮件提醒
     */
    private void sendTokenDisableMessage() {
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        // 新增意向客户，发送邮件提醒
        String message = String.format("%s 拉取数据时，\n检测到token已过期，请到管理平台 \n%s \n重新设置 **已开通会员** 的token信息",
                sdf.format(new Date()),
                "https://tea.glike.top");
        emailUtil.sendMessage("拉取TOKEN重置提醒", message);
    }
}
